package handlers

import (
	"database/sql"
	"net/http"

	"grpc-jwt-yonghurenzheng/v1.1_session_cookies/config"
	"grpc-jwt-yonghurenzheng/v1.1_session_cookies/models"

	"github.com/gin-gonic/gin"
	// "github.com/gorilla/sessions"
	"golang.org/x/crypto/bcrypt"
)

// Register 注册 (Gin 版本)
func Register(c *gin.Context) {
	if config.DB == nil {
        c.JSON(500, gin.H{"error": "DB 为空"})
        return
    }

	var user models.User
	// Gin 提供了更方便的 JSON 绑定方法，并自带验证
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求数据错误: " + err.Error()})
		return
	}

	hashed, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"})
		return
	}

	_, err = config.DB.Exec("INSERT INTO users (username, password, email) VALUES (?, ?, ?)",
		user.Username, string(hashed), user.Email)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "注册失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusCreated, gin.H{"message": "注册成功"})
}

// Login 登录 (Gin 版本)
func Login(c *gin.Context) {
	var loginReq models.User
	if err := c.ShouldBindJSON(&loginReq); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求 JSON 数据错误: " + err.Error()})
		return
	}

	if loginReq.Username == "" || loginReq.Password == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "用户名或密码不能为空"})
		return
	}

	var user models.User
	var hashedPwd string
	err := config.DB.QueryRow("SELECT id, username, password, email FROM users WHERE username = ?", loginReq.Username).
		Scan(&user.ID, &user.Username, &hashedPwd, &user.Email)

	if err == sql.ErrNoRows {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "用户不存在"})
		return
	} else if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "查询数据库失败: " + err.Error()})
		return
	}

	if err := bcrypt.CompareHashAndPassword([]byte(hashedPwd), []byte(loginReq.Password)); err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "密码错误"})
		return
	}

	// Session 核心逻辑 (与 Gin 集成)
	// gorilla/sessions 可以直接使用 gin.Context 中的 Request 和 Writer
	session, err := config.Store.Get(c.Request, "user-session")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取会话失败: " + err.Error()})
		return
	}

	session.Values["user_id"] = user.ID
	session.Values["username"] = user.Username
	session.Values["authenticated"] = true

	// 保存 session
	if err := session.Save(c.Request, c.Writer); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "保存会话失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message":  "登录成功",
		"user_id":  user.ID,
		"username": user.Username,
	})
}

// Logout 登出 (Gin 版本)
func Logout(c *gin.Context) {
	session, err := config.Store.Get(c.Request, "user-session")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取会话失败: " + err.Error()})
		return
	}

	session.Values["authenticated"] = false
	session.Options.MaxAge = -1

	if err := session.Save(c.Request, c.Writer); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "保存会话失败: " + err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "已成功登出"})
}

// Profile 获取用户信息 (Gin 版本)
// 这个 Handler 将被我们的认证中间件保护
func Profile(c *gin.Context) {
	// 从中间件设置的 context 中获取 session 和用户信息
	// 使用 MustGet，如果 key 不存在会 panic，确保中间件已正确设置
	userID := c.MustGet("userID").(int64)
	username := c.MustGet("username").(string)

	c.JSON(http.StatusOK, gin.H{
		"message":  "获取用户信息成功",
		"user_id":  userID,
		"username": username,
	})
}

// DeleteUser 删除当前登录的用户 (Gin 版本)
// 这个 Handler 也将被认证中间件保护
func DeleteUser(c *gin.Context) {
	userID := c.MustGet("userID").(int64)

	_, err := config.DB.Exec("DELETE FROM users WHERE id = ?", userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除用户失败: " + err.Error()})
		return
	}
	
	// 删除成功后，也需要销毁会话
	session, _ := config.Store.Get(c.Request, "user-session")
	session.Options.MaxAge = -1
	session.Save(c.Request, c.Writer)

	c.JSON(http.StatusOK, gin.H{"message": "您的账户已成功注销"})
}